﻿using System.IO;
using System.Web.UI;
using TA.Turbo.Controls;
using System.Collections.Generic;
using TA.DotNetUtils;
using System;

namespace TA.Turbo
{
	/// <summary>
	/// Markup template which can be instantiated and rendered.
	/// </summary>
	public abstract class MarkupTemplate : BaseMarkupTemplate
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="instance"></param>
		public MarkupTemplate(string name, TemplateInstance instance)
			: base(name)
		{
			this._instance = instance;
			this._container = this.CreateContainer();
			this._container.ID = name;
		}
		#endregion
		#region PROPS
		/// <summary>
		/// Gets the container control which will be used as the parent for initialized template.
		/// </summary>
		public Control Container { get { return _container; } }
		///// <summary>
		///// Gets the default control ID prefix (ie., "dataControl$Item" where "Item" is the name of the template).
		///// </summary>
		//public override string IdPrefix
		//{
		//  get
		//  {
		//    return this.Container.UniqueID;
		//  }
		//}
		/// <summary>
		/// Gets the array of all value controls in this template.
		/// </summary>
		/// <remarks>
		/// This array can be used to data binding or data serialization purposes, among other things.
		/// </remarks>
		public BaseValueDisplayControl[] ValueControls { get { return this._valueControls; } }
		#endregion
		#region METHODS
		/// <summary>
		/// Initializes this template by adding the proper include and instantiating the ITemplate in the container.
		/// </summary>
		public virtual void Init()
		{
			TPage.Current.Includes.Add(TA.Turbo.Script.Template);

			if (this._template != null)
			{
				this._template.InstantiateIn(this.Container);
			}

			List<BaseValueDisplayControl> valueControls = new List<BaseValueDisplayControl>();
			this.Container.ForEachRecursive<BaseValueDisplayControl>(delegate(BaseValueDisplayControl c)
			{
				if (c is INamingContainer && c != this.Container)
					return RecursiveResult.AvoidSubTree;

				if (!string.IsNullOrEmpty(c.Data.Field))
				{
					valueControls.Add(c);
				}

				return RecursiveResult.Continue;
			});

			this._valueControls = valueControls.ToArray();
		}
		/// <summary>
		/// Fills the specified list of PropertyPairs with properties found in all of the value controls in this templates.
		/// </summary>
		/// <param name="fields"></param>
		/// <param name="getPropertiesByPath"></param>
		public void Populate(List<PropertyPair> fields, Func<string, string[]> getPropertiesByPath)
		{
			foreach (BaseValueDisplayControl c in this.ValueControls)
			{
				string[] parts = getPropertiesByPath(c.Data.Field);
				IList<PropertyPair> curFields = fields;
				foreach (string onePart in parts)
				{
					PropertyPair ppExisting = null;
					foreach (PropertyPair pp in curFields)
					{
						if (string.Equals(pp.ObjectProperty, onePart))
						{
							ppExisting = pp;
							break;
						}
					}
					if (ppExisting == null)
					{
						ppExisting = new PropertyPair(onePart, null);
						curFields.Add(ppExisting);
					}
					curFields = ppExisting.Children;
				}

			}
		}
		/// <summary>
		/// Binds the value controls in this template using the specified value retrieval delegate.
		/// </summary>
		/// <param name="evaluate"></param>
		public virtual void Bind(Func<string, object> evaluate)
		{
			foreach (BaseValueDisplayControl valueControl in this.ValueControls)
			{
				object value = evaluate(valueControl.Data.Field);

				if (!string.IsNullOrEmpty(valueControl.Data.Format))
				{
					value = string.Format(valueControl.Data.Format, value);
				}
				else
				{
					if (valueControl.Data.BindingType == ValidationDataType.String)
						value = (value ?? "").ToString();
				}
				valueControl.GenericValue = value;

			}
		}
		#endregion
		#endregion
		#region INTERNAL
		#region CONST/STATIC
		#endregion
		#region VARS
		/// <summary>
		/// The template.
		/// </summary>
		protected ITemplate _template;
		internal TemplateInstance _instance;
		BaseTemplateContainer _container;
		BaseValueDisplayControl[] _valueControls;
		#endregion
		#region METHODS
		/// <summary>
		/// When implemented, creates the container which will receive the controls from the template.
		/// </summary>
		/// <returns></returns>
		protected abstract BaseTemplateContainer CreateContainer();
		/// <summary>
		/// Prepares the HTML markup and the initialization script for this template.
		/// </summary>
		protected override void PrepareMarkupAndScript()
		{
			string res = "";
			using (StringWriter sw = new StringWriter())
			{
				using (HtmlTextWriter tw = new HtmlTextWriter(sw))
				{
					_container.DoRender(tw);
					res = sw.ToString();
				}
			}

			this.SetMarkup(HtmlTools.GetMarkup(res));
			this.SetScript(HtmlTools.GetScript(res));
		}
		/// <summary>
		/// SerializeContents
		/// </summary>
		/// <param name="jw"></param>
		public override void SerializeContents(TA.JSON.JsonWriter jw)
		{
			base.SerializeContents(jw);

			//jw.PropertyName("I");
			//jw.Value(this.IdPrefix);
		}
		#endregion
		#endregion

	}
}